package com.lowca.news.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.JoinColumn;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

@Entity
@Table(name = "t_article", catalog = "com_lowca_news")
@org.hibernate.annotations.Entity(dynamicInsert = true, dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Article extends IdEntity implements Serializable {

	private static final long serialVersionUID = 1L;

	private String subject;
	private String content;// 文章正文，第1页
	private String summary;
	private Integer clickCount;
	private Integer commentCount;
	private Integer upCount;
	private Integer downCount;
	private Date lastUpdateTime;
	private Date publishTime;
	private User uploader;
	private User checker;
	private String author;
	private String source;
	private Boolean parseSummary = Boolean.FALSE;// 是否解析概要中的HTML代码，若解析，则不对summary进行截断处理
	private Boolean published = Boolean.TRUE;// 是否发表
	private Boolean containImage = Boolean.FALSE;
	private Boolean deleted = Boolean.FALSE;
	private Integer pageCount;// 文章内容的分页页数
	private Category category;
	private List<ArticleTag> articleTags = new ArrayList<ArticleTag>(0);
	private List<ArticleComment> articleComments = new ArrayList<ArticleComment>(
			0);// 文章评论
	private List<ArticleContent> articleContents = new ArrayList<ArticleContent>(
			0);// 文章正文，第2~N页

	public Article() {
		super();
	}

	public Article(String subject, String content, String summary,
			Boolean parseSummary, Integer clickCount, Integer commentCount,
			Integer upCount, Integer downCount, Date lastUpdateTime,
			Date publishTime, User uploader, User checker, String author,
			String source, Boolean published, Boolean containImage,
			Boolean deleted, Integer pageCount, Category category,
			List<ArticleTag> articleTags, List<ArticleComment> articleComments,
			List<ArticleContent> articleContents) {
		super();
		this.subject = subject;
		this.content = content;
		this.summary = summary;
		this.parseSummary = parseSummary;
		this.clickCount = clickCount;
		this.commentCount = commentCount;
		this.upCount = upCount;
		this.downCount = downCount;
		this.lastUpdateTime = lastUpdateTime;
		this.publishTime = publishTime;
		this.uploader = uploader;
		this.checker = checker;
		this.author = author;
		this.source = source;
		this.published = published;
		this.containImage = containImage;
		this.deleted = deleted;
		this.pageCount = pageCount;
		this.category = category;
		this.articleTags = articleTags;
		this.articleComments = articleComments;
		this.articleContents = articleContents;
	}

	@Column(name = "subject", length = 150, nullable = false)
	public String getSubject() {
		return subject;
	}

	public void setSubject(String subject) {
		this.subject = subject;
	}

	@Column(name = "content", length = 20000, nullable = false)
	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	@Column(name = "summary", length = 500)
	public String getSummary() {
		return summary;
	}

	public void setSummary(String summary) {
		this.summary = summary;
	}

	@Column(name = "parse_summary")
	public Boolean getParseSummary() {
		return parseSummary;
	}

	public void setParseSummary(Boolean parseSummary) {
		this.parseSummary = parseSummary;
	}

	@Column(name = "click_count", length = 8)
	public Integer getClickCount() {
		return clickCount;
	}

	public void setClickCount(Integer clickCount) {
		this.clickCount = clickCount;
	}

	@Column(name = "comment_count", length = 8)
	public Integer getCommentCount() {
		return commentCount;
	}

	public void setCommentCount(Integer commentCount) {
		this.commentCount = commentCount;
	}

	@Column(name = "up_count", length = 8)
	public Integer getUpCount() {
		return upCount;
	}

	public void setUpCount(Integer upCount) {
		this.upCount = upCount;
	}

	@Column(name = "down_count", length = 8)
	public Integer getDownCount() {
		return downCount;
	}

	public void setDownCount(Integer downCount) {
		this.downCount = downCount;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "last_update_time", length = 19)
	public Date getLastUpdateTime() {
		return lastUpdateTime;
	}

	public void setLastUpdateTime(Date lastUpdateTime) {
		this.lastUpdateTime = lastUpdateTime;
	}

	@Temporal(TemporalType.TIMESTAMP)
	@Column(name = "publish_time", length = 19)
	public Date getPublishTime() {
		return publishTime;
	}

	public void setPublishTime(Date publishTime) {
		this.publishTime = publishTime;
	}

	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
	@JoinColumn(name = "uploader_id")
	public User getUploader() {
		return uploader;
	}

	public void setUploader(User uploader) {
		this.uploader = uploader;
	}

	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
	@JoinColumn(name = "checker_id")
	public User getChecker() {
		return checker;
	}

	public void setChecker(User checker) {
		this.checker = checker;
	}

	@Column(name = "author", length = 20)
	public String getAuthor() {
		return author;
	}

	public void setAuthor(String author) {
		this.author = author;
	}

	@Column(name = "source", length = 30)
	public String getSource() {
		return source;
	}

	public void setSource(String source) {
		this.source = source;
	}

	@Column(name = "published")
	public Boolean getPublished() {
		return published;
	}

	public void setPublished(Boolean published) {
		this.published = published;
	}

	@Column(name = "contain_image")
	public Boolean getContainImage() {
		return containImage;
	}

	public void setContainImage(Boolean containImage) {
		this.containImage = containImage;
	}

	@Column(name = "deleted")
	public Boolean getDeleted() {
		return deleted;
	}

	public void setDeleted(Boolean deleted) {
		this.deleted = deleted;
	}

	@Column(name = "page_count")
	public Integer getPageCount() {
		return pageCount;
	}

	public void setPageCount(Integer pageCount) {
		this.pageCount = pageCount;
	}

	@ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
	@JoinColumn(name = "category_id")
	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "article")
	@OrderBy("sortValue ASC")
	public List<ArticleTag> getArticleTags() {
		return articleTags;
	}

	public void setArticleTags(List<ArticleTag> articleTags) {
		this.articleTags = articleTags;
	}

	@ManyToMany
	@JoinTable(name = "t_article_has_comment", joinColumns = { @JoinColumn(name = "article_id") }, inverseJoinColumns = { @JoinColumn(name = "article_comment_id") })
	@Fetch(FetchMode.SUBSELECT)
	@OrderBy("publishTime DESC")
	public List<ArticleComment> getArticleComments() {
		return articleComments;
	}

	public void setArticleComments(List<ArticleComment> articleComments) {
		this.articleComments = articleComments;
	}

	@OneToMany(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY, mappedBy = "article")
	@OrderBy("sortValue ASC")
	public List<ArticleContent> getArticleContents() {
		return articleContents;
	}

	public void setArticleContents(List<ArticleContent> articleContents) {
		this.articleContents = articleContents;
	}

	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

	public boolean equals(Object other) {
		if (this == other)
			return true;
		if (!(other instanceof Article))
			return false;
		final Article article = (Article) other;
		if (!getSubject().equals(article.getSubject()))
			return false;
		if (!getContent().equals(article.getContent()))
			return false;
		if (getCategory() != null
				&& !getCategory().equals(article.getCategory()))
			return false;
		return true;
	}

	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + getSubject().hashCode();
		result = prime * result + getContent().hashCode();
		result = prime * result
				+ ((getCategory() == null) ? 0 : getCategory().hashCode());
		return result;
	}

}
